﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;

namespace Weka
{
    internal static class FieldDeserialiserProviderMessage
    {
        public static FieldDeserialiserProviderMessage<T, MT> Create<T, MT>(ObjectDeserialiserProviderCreator dzx, System.Reflection.MethodInfo methodInfo)
        where MT : class, new()
        {
            FieldDeserialiserProviderMessage<T, MT> q = new FieldDeserialiserProviderMessage<T, MT>();

            q.ObjectDeserialiserProvider = (ObjectDeserialiserProvider<MT>)dzx.GetObjectDeserialiserProvider();

            q.Writer = methodInfo.CreateActionDelegate<T, MT>();
            return q;
        }
    }


    internal class FieldDeserialiserProviderMessage<T, MT> : FieldDeserialiserProvider<T, MT>//MT is Message Type
        where MT : class, new()
    {
        internal ObjectDeserialiserProvider<MT> ObjectDeserialiserProvider { set; get; }

        public override FieldDeserialiser<T> CreateFieldDeserialiser()
        {
            return new FieldDeserialiserMessage<T, MT>() { ObjectDeserialiser = ObjectDeserialiserProvider.Create(), Writer = Writer };
        }

    }

    internal class FieldDeserialiserMessage<T, MT> : FieldDeserialiser<T, MT>//MT is Message Type
        where MT : class, new()
    {
        public ObjectDeserialiser<MT> ObjectDeserialiser { get; set; }

        public override void ReadWriteValue(T value, StreamReada streamReader)
        {
            if (Header == 1)
                Writer(value, ObjectDeserialiser.FromData(streamReader));
        }

        public override void ReadHeader(StreamReada streamReader)
        {
            Header = streamReader.HeaderReadBit();
        }
    }




    internal static class FieldDeserialiserProviderMessageList
    {
        public static FieldDeserialiserProviderMessageList<T, MT> Create<T, MT>(ObjectDeserialiserProviderCreator dzx, System.Reflection.MethodInfo methodInfo)
        where MT : class, new()
        {
            FieldDeserialiserProviderMessageList<T, MT> q = new FieldDeserialiserProviderMessageList<T, MT>();

            q.ObjectDeserialiserProvider = (ObjectDeserialiserProvider<MT>)dzx.GetObjectDeserialiserProvider();

            q.Writer = methodInfo.CreateActionDelegate<T, IEnumerable<MT>>();
            return q;
        }
    }



    internal class FieldDeserialiserProviderMessageList<T, MT> : FieldDeserialiserProvider<T, IEnumerable<MT>>//MT is Message Type
        where MT : class, new()
    {
        public ObjectDeserialiserProvider<MT> ObjectDeserialiserProvider { get; set; }

        public override FieldDeserialiser<T> CreateFieldDeserialiser()
        {
            return new FieldDeserialiserMessageList<T, MT>() { ObjectDeserialiser = ObjectDeserialiserProvider.Create(), Writer = Writer };
        }

    }



    internal class FieldDeserialiserMessageList<T, MT> : FieldDeserialiser<T, IEnumerable<MT>>//MT is Message Type
        where MT : class, new()
    {
        public ObjectDeserialiser<MT> ObjectDeserialiser { get; set; }

        public override void ReadHeader(StreamReada sr)
        {
            Header = sr.HeaderReadBit();
        }

        public override void ReadWriteValue(T value, StreamReada sr)
        {
            if (Header == 0) return;

            List<MT> list = new List<MT>();
            while (sr.HeaderReadBit() == 1)
            {
                bool isNull=sr.HeaderReadBit() == 0;
                if (isNull)
                {
                    list.Add(null);
                }
                else
                {
                    MT v = ObjectDeserialiser.FromData(sr);
                    list.Add(v);
                }
                //TODO?????                 sr.HeaderClear();
            }
            sr.HeaderClear();

            Writer(value, list);
        }
    }
}
